#include "header.h"
const char *building_version=__VERSION_ID__;
void printHelp()
{
    cout << "Usage: updateNeigh [-vh] -c configFile" << endl;
}

void print_building_info(void)
{ 
    printf("Building version:\t%s\nBuilding time:\t\t%s %s\n", building_version, __DATE__, __TIME__);
}
void getSimFromDB(vector<mypair> &sim, int qId, DBBase &db);
ConfigFile g_config;
RelatedQuestions g_relateQuestions;
DBBase g_db;

int main (int argc, char* argv[])
{
    //cout << argc << endl;
    const char *optstring = "hvc:";
    char configFile[MAX_FILE_NAME_LEN];
    int optch = 0;
    int doc_num = 0;
    int maxStep = 0;
    const char *inLinkFile, *relateFile;
    string simFun;
    while ((optch = getopt(argc, argv, optstring)) != -1) {
        switch (optch) {
            case 'c':
                strcpy(configFile, optarg);
                break;
            case 'h':
                printHelp();
                return 0;
            case 'v':
                print_building_info();
                return 0;
        }
    }
    if (strlen(configFile) < 1) {
        if (argc < 6) {
            printHelp();
            exit(1);
        }
        inLinkFile = "";
        relateFile = "";
    }
    else {
        g_config.load(configFile);
        doc_num = atoi(g_config.Value("section_1", "doc_num").c_str());
        inLinkFile = g_config.Value("section_1", "inlink_file").c_str();
        relateFile = g_config.Value("section_1", "relateQuestion_file").c_str();
        maxStep = atoi(g_config.Value("section_1", "max_step").c_str());
    }
   
    const int neighb_num = NEIGHB_NUM;
    //host,db,user,pass
    int conRet = g_db.openConnection(g_config.Value("database", "server").c_str(),
            g_config.Value("database", "dbname").c_str(),
            g_config.Value("database", "user").c_str(),
            g_config.Value("database", "password").c_str());
    if (200 != conRet) {
        cout << dberror(conRet);
        exit(1);
    }
  
    //load inlink and relate questions 
    g_relateQuestions.load(relateFile, inLinkFile, doc_num, neighb_num);
    vector<mypair> sim; 
    int tmpInlinkNum = 0;
    char buff[5];
    string dstDir = get_dir(g_config.Value("section_1", "relateQuestion_file"));
    string tableName = g_config.Value("database","table_name");
    SimTable simTable(&g_db, tableName.c_str());
    //calculate  the sim and sort in a heap
    for (int step = 0; step < maxStep; ++step) { //for every step
        sprintf(buff,"%d",step);
        ofstream out((dstDir+"/"+ tableName+ "_step_"+buff).c_str());
        for (int i=1; i <= doc_num; ++i) {       // for every question
            //getSimFromDB(sim, i, g_db); //one similarity one line
            simTable.getSimFromDB(sim, i); //one question one line
            //for evey neighbor, update sim
            vector<mypair>::iterator it = sim.begin();
            vector<mypair>::iterator end = sim.end();
            for (; it !=end; ++it) {
                tmpInlinkNum = g_relateQuestions.getInlink(it->first);
                it->second = inverseInLink(it->second, tmpInlinkNum);
            }

            //sort the new sim vector
            vector<mypair> knns = getKmax(sim, NEIGHB_NUM);
            sort_heap(knns.begin(), knns.end(), comparator);

            //update the inlink and neighbor
            g_relateQuestions.updateRelatedQuestions(i, knns);
            if (i % 100 == 0) {
                cout << "step:" << step << ", docNum:" << i << endl;
                //exit(1);
            }
            int knnsSize = knns.size();
            out << i << " ";
            for (int k = 0; k < knnsSize; ++k) {
                if (k >=NEIGHB_NUM) break;
                if (0==k) out << knns[k].first << "@" << knns[k].second;
                else out << "," << knns[k].first << "@" << knns[k].second;
            }
            out << endl;
            knns.clear();
            sim.clear();
        }
        out.close();
        //@ToDO::store the result of every step
        cout << "step: " << step << " finished!" << endl;
    }
    
    g_db.disconnect();
    return 0;
}

void getSimFromDB(vector<mypair> &sim, int qId, DBBase &db)
{
    ostringstream os;
    MYSQL_ROW       mysqlRow;
    os << "select qId2,lsa from Similarity where qId1=" << qId;
    MYSQL_RES *mysqlResult = db.query(os.str().c_str());
    //int numFields = mysql_num_fields(mysqlResult);
    while ((mysqlRow = mysql_fetch_row(mysqlResult))) {// row pointer in the result set
        //for(int ii=0; ii < numFields; ii++) {
        //    printf("%s\t", mysqlRow[ii] ? mysqlRow[ii] : "NULL");  // Not NULL then print
        //}
        sim.push_back(make_pair(atoi(mysqlRow[0]), atof(mysqlRow[1])));
        //printf("\n");
    }
    if(mysqlResult) {
        mysql_free_result(mysqlResult);
    }
}
